﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PagedList;
using RGoodSW.Logger.Interfaces;
using RGoodSW.Logger.MvcHelper.Models;
using SWS = System.Web.Security;
using CodeCamp.Infrastructure;
using CodeCamp.Model;
using CodeCamp.Models.EventMgmt;
using CodeCamp.Models.Shared;
using CCM = CodeCamp.Model;

namespace CodeCamp.Controllers
{
    [CustomAuthorize(Roles = CCRoles.RoleNames.BigCheeze)]
    public class EventMgmtController : ControllerBase
    {
        private static class Tags
        {
            internal const string defaultLocalTimeConversionHours = "defaultSiteUserLocalTimeConversionHours";
            internal const string defaultLocalTimeZone = "defaultSiteUserLocalTimeZone";
            internal const string savedFilterModel = "siteUserSavedFilterModel";
        }

        public EventMgmtController(IDefaultValueProvider defaultValueProvider, ILoggerExtended logger)
            : base(defaultValueProvider, logger)
        {
        }


        //
        // GET: /EventMgmt/

        public ActionResult Index(string eventName)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(event_);

                EventMgmtIndexViewModel model = new EventMgmtIndexViewModel();
                var eventList = repository.EFContext.Events.OrderBy(e => e.DisplaySortOrder).ToList();
                foreach(var ev in eventList)
                {
                    EventListViewModel.Event eventModel = new EventListViewModel.Event
                    {
                        Id = ev.Id,
                        AgendaIsPublic = ev.AgendaIsPublic,
                        DisplayDate = ev.DisplayDate,
                        DisplayName = ev.DisplayName,
                        DisplaySortOrder = ev.DisplaySortOrder,
                        EventStartDate = ev.EventStartDate,
                        EventIsPublic = ev.EventIsPublic,
                        RegistrationUrl = ev.RegistrationUrl,
                        SchedulePdfUrl = ev.SchedulePdfUrl,
                        ScheduleIsPublic = ev.ScheduleIsPublic,
                        ScheduleVisibleToPresenters = ev.ScheduleVisibleToPresenters,
                        ShortName = ev.ShortName
                    };
                    model.EventList.List.Add(eventModel);
                }
                SetSharedEventProperties(event_, model, repository);

                return View(model);
            }
        }

        public ActionResult AddEvent(string eventName)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var currentEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(currentEvent);

                EventMgmtEventViewModel model = new EventMgmtEventViewModel();
                SetSharedEventProperties(currentEvent, model, repository);
                model.EditModel = new EventEditViewModel();
                model.EditModel.SessionSubmissionsOpen = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
                model.EditModel.SessionSubmissionsClose = MinSqlTime;
                model.EditModel.EventStartDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);

                return View(model);
            }
        }

        //public void SetupNonpublicEventPreviewRole(System.Security.Principal.IPrincipal principal,
        //    string oldNonpublicEventPreviewRoleName, string newNonpublicEventPreviewRoleName)
        //{
        //    if (!string.IsNullOrWhiteSpace(newNonpublicEventPreviewRoleName))
        //    {
        //        string[] allRoles = SWS.Roles.GetAllRoles();
        //        if (!allRoles.Contains(newNonpublicEventPreviewRoleName))
        //        {
        //            SWS.Roles.CreateRole(newNonpublicEventPreviewRoleName);
        //            if (principal.IsInRole(CCRoles.RoleNames.BigCheeze))
        //            {
        //                SWS.Roles.AddUserToRole(principal.Identity.Name, newNonpublicEventPreviewRoleName);
        //            }
        //        }
        //    }
        //}

        protected void SetupNonpublicEventPreviewRole(SiteUser siteUser,
            CodeCampDataRepository ccdr,
            string oldNonpublicEventPreviewRoleName, string newNonpublicEventPreviewRoleName)
        {
            if (!string.IsNullOrWhiteSpace(newNonpublicEventPreviewRoleName))
            {
                int roleId = ccdr.GetRoleId(newNonpublicEventPreviewRoleName);
                if (roleId == 0)
                {
                    Role role = ccdr.AddRole(newNonpublicEventPreviewRoleName);
                    if (this.User.Identity.IsAuthenticated && this.User.IsInRole(CCRoles.RoleNames.BigCheeze))
                    {
                        string fullName = string.Concat(siteUser.FirstName, " ", siteUser.LastName).Trim();
                        ccdr.AddSiteUserToRole(siteUser, LogName(siteUser), newNonpublicEventPreviewRoleName, false);
                    }
                    ccdr.Save();
                }
            }
        }

        //[Authorize(Roles = CCRoles.RoleNames.BigCheeze)] //Property of class
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AddEvent(EventEditViewModel model, string eventName, int id)
        {
            using (var repository = new CodeCampDataRepository())
            {
                //try
                //{
                    var currentEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                    var siteUser = GetSiteUser(repository, this.User, true);
                    SetSharedViewBagProperties(currentEvent);

                    Event ev = null;

                    if (ModelState.IsValid)
                    {
                        if (id != 0)
                        {
                            ev = repository.GetEvent(id, false);
                            if (ev == null)
                                return RedirectToAction("Index");
                            if ((model == null) || (model.Id != id) || (model.Id != ev.Id) || (model.ShortName != ev.ShortName))
                                return RedirectToAction("Index");
                        }
                        else
                        {
                            ev = new Event();
                            ev.ShortName = model.ShortName;
                        }
                        ev.AgendaIsPublic = model.AgendaIsPublic;
                        ev.DisconnectedPresenterProfileConnectionAllowed = model.DisconnectedPresenterProfileConnectionAllowed;
                        ev.DisplayDate = model.DisplayDate;
                        ev.DisplayLocation = model.DisplayLocation;
                        ev.DisplayName = model.DisplayName;
                        ev.DisplaySortOrder = model.DisplaySortOrder;
                        ev.EventIsPublic = model.EventIsPublic;
                        ev.EventStartDate = model.EventStartDate;
                        ev.NonPublicEventPreviewRole = model.NonPublicEventPreviewRole;
                        ev.PriorEventProfileReuseAllowed = model.PriorEventProfileReuseAllowed;
                        ev.RegistrationUrl = model.RegistrationUrl;
                        ev.SchedulePdfUrl = model.SchedulePdfUrl;
                        ev.SessionSubmissionsClose = FixupDateTimeForSqlMin(model.SessionSubmissionsClose);
                        ev.SessionSubmissionsOpen = FixupDateTimeForSqlMin(model.SessionSubmissionsOpen);
                        ev.ScheduleIsPublic = model.ScheduleIsPublic;
                        ev.ScheduleVisibleToPresenters = model.ScheduleVisibleToPresenters;

                        if (id == 0)
                        {
                            repository.EFContext.Events.Add(ev);
                        }

                        repository.Save();

                        if (!string.IsNullOrWhiteSpace(ev.NonPublicEventPreviewRole))
                        {
                            SetupNonpublicEventPreviewRole(siteUser, repository, null, ev.NonPublicEventPreviewRole);
                        }

                        return RedirectToAction("Index");
                    }

                    EventMgmtEventViewModel viewModel = new EventMgmtEventViewModel();
                    SetSharedEventProperties(currentEvent, viewModel, repository);
                    viewModel.EditModel = model;
                    return View(viewModel);
                //}
                //catch (Exception ex)
                //{
                //    TempData.Add(TempDataKeys.ErrorMessage, "Error saving new event.");
                //    LogException("EventMgmt/AddEvent POST", ex);
                //    return RedirectToAction("Index", "Errors");
                //}
            }
        }

        public ActionResult EditEvent(string eventName, int id)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var currentEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(currentEvent);
                
                Event ev = repository.GetEvent(id, false);
                if (ev == null)
                    return RedirectToAction("Index");

                EventMgmtEventViewModel model = new EventMgmtEventViewModel();
                SetSharedEventProperties(currentEvent, model, repository);

                model.EditModel = new EventEditViewModel
                {
                    Id = ev.Id,
                    AgendaIsPublic = ev.AgendaIsPublic,
                    DisconnectedPresenterProfileConnectionAllowed = ev.DisconnectedPresenterProfileConnectionAllowed,
                    DisplayDate = ev.DisplayDate,
                    DisplayLocation = ev.DisplayLocation,
                    DisplayName = ev.DisplayName,
                    DisplaySortOrder = ev.DisplaySortOrder,
                    EventIsPublic = ev.EventIsPublic,
                    EventStartDate = ev.EventStartDate,
                    NonPublicEventPreviewRole = ev.NonPublicEventPreviewRole,
                    PriorEventProfileReuseAllowed = ev.PriorEventProfileReuseAllowed,
                    RegistrationUrl = ev.RegistrationUrl,
                    SchedulePdfUrl = ev.SchedulePdfUrl,
                    SessionSubmissionsOpen = ev.SessionSubmissionsOpen,
                    SessionSubmissionsClose = ev.SessionSubmissionsClose,
                    ShortName = ev.ShortName,
                    ScheduleIsPublic = ev.ScheduleIsPublic,
                    ScheduleVisibleToPresenters = ev.ScheduleVisibleToPresenters
                };

                return View(model);
            }
        }

        //[Authorize(Roles = CCRoles.RoleNames.BigCheeze)] //Property of class
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult EditEvent(EventEditViewModel model, string eventName, int id)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var currentEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                var siteUser = GetSiteUser(repository, this.User, true);
                SetSharedViewBagProperties(currentEvent);

                Event ev = repository.GetEvent(id, false);
                if (ev == null)
                    return RedirectToAction("Index");
                if ((model == null) || (model.Id != id) || (model.Id != ev.Id) || (model.ShortName != ev.ShortName))
                    return RedirectToAction("Index");

                if (ModelState.IsValid)
                {
                    ////Handle case where annotation of [Required] and [MinLength(0)] not working.
                    //if (string.IsNullOrEmpty(model.DisplayDate))
                    //    model.DisplayDate = " ";
                    //if (string.IsNullOrEmpty(model.DisplayLocation))
                    //    model.DisplayLocation = " ";
                    //if (string.IsNullOrEmpty(model.RegistrationUrl))
                    //    model.RegistrationUrl = " ";
                    string oldNonPublicEventPreviewRole = ev.NonPublicEventPreviewRole;

                    ev.AgendaIsPublic = model.AgendaIsPublic;
                    ev.DisplayDate = model.DisplayDate;
                    ev.DisplayLocation = model.DisplayLocation;
                    ev.DisplayName = model.DisplayName;
                    ev.DisplaySortOrder = model.DisplaySortOrder;
                    ev.EventIsPublic = model.EventIsPublic;
                    ev.ScheduleIsPublic = model.ScheduleIsPublic;
                    ev.ScheduleVisibleToPresenters = model.ScheduleVisibleToPresenters;
                    ev.RegistrationUrl = model.RegistrationUrl;
                    ev.SchedulePdfUrl = model.SchedulePdfUrl;
                    ev.SessionSubmissionsClose = model.SessionSubmissionsClose;
                    ev.SessionSubmissionsOpen = model.SessionSubmissionsOpen;
                    ev.EventStartDate = model.EventStartDate;
                    ev.DisconnectedPresenterProfileConnectionAllowed = model.DisconnectedPresenterProfileConnectionAllowed;
                    ev.PriorEventProfileReuseAllowed = model.PriorEventProfileReuseAllowed;
                    ev.NonPublicEventPreviewRole = model.NonPublicEventPreviewRole;

                    repository.Save();

                    SetupNonpublicEventPreviewRole(siteUser, repository, oldNonPublicEventPreviewRole, ev.NonPublicEventPreviewRole);

                    return RedirectToAction("Index");
                }

                EventMgmtEventViewModel viewModel = new EventMgmtEventViewModel();
                SetSharedEventProperties(currentEvent, viewModel, repository);
                viewModel.EditModel = model;
                return View(viewModel);
            }
        }

        private SiteUserEditModel GetSiteUserEditModel(SiteUser siteUser)
        {
            SiteUserEditModel model = new SiteUserEditModel
            {
                CreatedBy = siteUser.CreatedBy,
                CreatedUTC = siteUser.CreatedUTC,
                EmailAddress = siteUser.EmailAddress,
                FirstName = siteUser.FirstName,
                SiteUserId = siteUser.Id,
                IpAtSignup = siteUser.IpAtSignup,
                IsApproved = siteUser.IsApproved,
                IsLockedOut = siteUser.IsLockedOut,
                LastLoginUTC = siteUser.LastLoginUTC,
                LastName = siteUser.LastName,
                LastOnlineActivityUTC = siteUser.LastOnlineActivityUTC,
                UpdatedBy = siteUser.UpdatedBy,
                UpdatedUTC = siteUser.UpdatedUTC,
                UserClaimEmailAddress = siteUser.UserClaimEmailAddress,
                UserIdentityClaim = siteUser.UserIdentityClaim,
                UserIdentityClaimType = siteUser.UserIdentityClaimType,
                UserIdentityIssuer = siteUser.UserIdentityIssuer,
                UserIdentityProvider = siteUser.UserIdentityProvider,
                Version = siteUser.Version
            };
            return model;
        }

        private void GetSiteUserEventPresenterList(SiteUser siteUser, SiteUserEditModel model)
        {
            foreach (var presenter in siteUser.Presenters)
            {
                EventPresenterViewModel epvm = new EventPresenterViewModel
                {
                    EventId = presenter.EventId,
                    EventShortName = presenter.Event.ShortName,
                    PresenterId = presenter.Id
                };
                model.PresenterEvents.Add(epvm);
            }
        }

        private void GetSiteUserRoleProperties(CodeCampDataRepository ccdr, int eventId, string nonPublicEventPreviewRole, SiteUserEditModel model)
        {
            model.IsBigCheeze = ccdr.SiteUserIsInRole(model.SiteUserId, CCRoles.RoleNames.BigCheeze);
            model.IsEventContentEditor = ccdr.SiteUserIsInEventRole(model.SiteUserId, eventId, CCRoles.RoleNames.EventContentEditor);
            model.IsEventTrackLead = ccdr.SiteUserIsInEventRole(model.SiteUserId, eventId, CCRoles.RoleNames.EventTrackLead);
            model.IsPresenter = ccdr.SiteUserIsInRole(model.SiteUserId, CCRoles.RoleNames.Presenter);
            if (!string.IsNullOrWhiteSpace(nonPublicEventPreviewRole))
            {
                model.EventHasNonPublicPreviewRole = true;
                model.IsEventPreviewer = ccdr.SiteUserIsInRole(model.SiteUserId, nonPublicEventPreviewRole);
                model.NonPublicEventPreviewRole = nonPublicEventPreviewRole;
            }
        }

#if USE_MEMBERSHIP
        private void AddMembershipProperties(SiteUserEditModel model)
        {
            if (CodeCampDataRepository.IdentityIssuers.CodeCamp.Equals(model.UserIdentityIssuer)
                && CodeCampDataRepository.IdentityProviders.CodeCamp.Equals(model.UserIdentityProvider)
                && CodeCampDataRepository.ClaimTypes.username.Equals(model.UserIdentityClaimType))
            {
                SWS.MembershipUser user = SWS.Membership.Provider.GetUser(model.UserIdentityClaim, false);
                if (user != null)
                {
                    model.MemberCreationDate = user.CreationDate;
                    model.MemberEmailAddress = user.Email;
                    model.MemberIsApproved = user.IsApproved;
                    model.MemberIsLockedOut = user.IsLockedOut;
                    model.MemberIsOnline = user.IsOnline;
                    model.MemberLastActivityDate = user.LastActivityDate;
                    model.MemberLastLoginDate = user.LastLoginDate;
                    model.MemberUsername = user.UserName;
                    model.SiteUserHasMembership = true;
                }
            }
        }
#endif

        public ActionResult SiteUserDetail(string eventName, int id)
        {
            SetLoggerThreadContextData();
            using (CodeCampDataRepository repository = new CodeCampDataRepository())
            {
                try
                {
                    var siteUser = repository.GetSiteUser(id);
                    if (siteUser == null)
                        return RedirectToAction("SiteUsers");

                    var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);
                    SetSharedViewBagProperties(ccEvent);

                    SiteUserEditViewModel viewModel = new SiteUserEditViewModel();
                    SetSharedEventProperties(ccEvent, viewModel, repository);
                    viewModel.SiteUserEditModel = GetSiteUserEditModel(siteUser);
                    GetSiteUserEventPresenterList(siteUser, viewModel.SiteUserEditModel);
                    GetSiteUserRoleProperties(repository, ccEvent.Id, ccEvent.NonPublicEventPreviewRole, viewModel.SiteUserEditModel);
#if USE_MEMBERSHIP
                    AddMembershipProperties(viewModel.SiteUserEditModel);
#endif
                    return View(viewModel);
                }
                catch (Exception ex)
                {
                    LogException("EventMgmt/SiteUserDetail", ex);
                    return View("Error2");
                }
            }
        }

        public ActionResult SiteUserEdit(string eventName, int id)
        {
            SetLoggerThreadContextData();
            using (CodeCampDataRepository repository = new CodeCampDataRepository())
            {
                try
                {
                    var siteUser = repository.GetSiteUser(id);
                    if (siteUser == null)
                        return RedirectToAction("SiteUsers");

                    var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);
                    SetSharedViewBagProperties(ccEvent);

                    SiteUserEditViewModel viewModel = new SiteUserEditViewModel();
                    SetSharedEventProperties(ccEvent, viewModel, repository);
                    viewModel.SiteUserEditModel = GetSiteUserEditModel(siteUser);
                    GetSiteUserRoleProperties(repository, ccEvent.Id, ccEvent.NonPublicEventPreviewRole, viewModel.SiteUserEditModel);
#if USE_MEMBERSHIP
                    AddMembershipProperties(viewModel.SiteUserEditModel);
#endif

                    return View(viewModel);
                }
                catch (Exception ex)
                {
                    LogException("EventMgmt/SiteUserEdit", ex);
                    return View("Error2");
                }
            }
        }

        //[Authorize(Roles = CCRoles.RoleNames.BigCheeze)] //Property of class
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SiteUserEdit(SiteUserEditModel model, string eventName, int id)
        {
            SetLoggerThreadContextData();
            using (CodeCampDataRepository repository = new CodeCampDataRepository())
            {
                try
                {
                    var siteUserBeingEdited = repository.GetSiteUser(id);
                    if (siteUserBeingEdited == null)
                        return RedirectToAction("SiteUsers");
                    var siteUserPerformingEdit = GetSiteUser(repository, this.User);
                    if (siteUserPerformingEdit == null)
                        return RedirectToAction("SiteUsers");

                    string updateUsername = UpdateUser(siteUserPerformingEdit);

                    var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);
                    SetSharedViewBagProperties(ccEvent);

                    SiteUserEditViewModel viewModel = new SiteUserEditViewModel();
                    SetSharedEventProperties(ccEvent, viewModel, repository);

                    if (ModelState.IsValid)
                    {
                        bool siteUserChanged = false;
                        if (!siteUserBeingEdited.FirstName.Equals(model.FirstName))
                        {
                            siteUserBeingEdited.FirstName = model.FirstName;
                            siteUserChanged = true;
                        }
                        if (!siteUserBeingEdited.LastName.Equals(model.LastName))
                        {
                            siteUserBeingEdited.LastName = model.LastName;
                            siteUserChanged = true;
                        }
                        if (!siteUserBeingEdited.EmailAddress.Equals(model.EmailAddress))
                        {
                            siteUserBeingEdited.EmailAddress = model.EmailAddress;
                            siteUserChanged = true;
                        }

                        string roleName = CCRoles.RoleNames.BigCheeze;
                        bool siteUserIsInRole = repository.SiteUserIsInRole(siteUserBeingEdited.Id, roleName);
                        bool modelUserIsInRole = model.IsBigCheeze;
                        if (siteUserIsInRole != modelUserIsInRole)
                        {
                            ChangeUserInRole(repository, siteUserBeingEdited, true, roleName, modelUserIsInRole, updateUsername, ref siteUserChanged);
                        }

                        roleName = CCRoles.RoleNames.EventContentEditor;
                        siteUserIsInRole = repository.SiteUserIsInEventRole(siteUserBeingEdited.Id, ccEvent.Id, roleName);
                        modelUserIsInRole = model.IsEventContentEditor;
                        if (siteUserIsInRole != modelUserIsInRole)
                        {
                            ChangeUserInEventRole(repository, siteUserBeingEdited, ccEvent, true, roleName, modelUserIsInRole, updateUsername, ref siteUserChanged);
                        }

                        roleName = CCRoles.RoleNames.EventTrackLead;
                        siteUserIsInRole = repository.SiteUserIsInEventRole(siteUserBeingEdited.Id, ccEvent.Id, roleName);
                        modelUserIsInRole = model.IsEventTrackLead;
                        if (siteUserIsInRole != modelUserIsInRole)
                        {
                            ChangeUserInEventRole(repository, siteUserBeingEdited, ccEvent, true, roleName, modelUserIsInRole, updateUsername, ref siteUserChanged);
                        }

                        roleName = CCRoles.RoleNames.Presenter;
                        siteUserIsInRole = repository.SiteUserIsInRole(siteUserBeingEdited.Id, roleName);
                        modelUserIsInRole = model.IsPresenter;
                        if (siteUserIsInRole != modelUserIsInRole)
                        {
                            ChangeUserInRole(repository, siteUserBeingEdited, true, roleName, modelUserIsInRole, updateUsername, ref siteUserChanged);
                        }
                        if (!string.IsNullOrWhiteSpace(ccEvent.NonPublicEventPreviewRole))
                        {
                            roleName = ccEvent.NonPublicEventPreviewRole;
                            siteUserIsInRole = repository.SiteUserIsInRole(siteUserBeingEdited.Id, roleName);
                            modelUserIsInRole = model.IsEventPreviewer;
                            if (siteUserIsInRole != modelUserIsInRole)
                            {
                                ChangeUserInRole(repository, siteUserBeingEdited, true, roleName, modelUserIsInRole, updateUsername, ref siteUserChanged);
                            }
                        }
                        if (siteUserChanged)
                        {
                            siteUserBeingEdited.UpdatedBy = updateUsername;
                            siteUserBeingEdited.UpdatedUTC = DateTime.UtcNow;
                            repository.Save();
                            return RedirectToAction("SiteUserDetail", new { id = model.SiteUserId });
                        }
                        model.EventHasNonPublicPreviewRole = !string.IsNullOrWhiteSpace(ccEvent.NonPublicEventPreviewRole);
                    }
                    viewModel.SiteUserEditModel = model;

                    return View(viewModel);
                }
                catch (Exception ex)
                {
                    LogException("EventMgmt/SiteUserEdit", ex);
                    return View("Error2");
                }
            }
        }

        private void ChangeUserInRole(CodeCampDataRepository repository, SiteUser roleSiteUser,
            bool createRoleIfNotExists, string roleName,
            bool modelUserIsInRole, string createUser, ref bool siteUserChanged)
        {
            if (modelUserIsInRole)
            {
                repository.AddSiteUserToRole(roleSiteUser, createUser, roleName, true);
                siteUserChanged = true;
            }
            else
            {
                UserInRole uir = repository.GetUserInRole(roleSiteUser.Id, roleName);
                if (uir != null)
                {
                    repository.EFContext.UsersInRoles.Remove(uir);
                    siteUserChanged = true;
                }
            }
        }

        //private void ChangeUserInEventRole(CodeCampDataRepository ccdr, SiteUser siteUser, Event ccEvent,
        //    string roleName, bool modelUserIsInRole, ref bool siteUserChanged)
        //{
        //    ChangeUserInEventRole(ccdr, siteUser, ccEvent, false, roleName, modelUserIsInRole, ref siteUserChanged);
        //}

        private void ChangeUserInEventRole(CodeCampDataRepository ccdr, SiteUser roleSiteUser, Event ccEvent, 
            bool createRoleIfNotExists, string roleName,
            bool modelUserIsInRole, string createUser, ref bool siteUserChanged)
        {
            if (modelUserIsInRole)
            {
                ccdr.AddSiteUserToEventRole(ccEvent, roleSiteUser, createUser, roleName, createRoleIfNotExists);
                siteUserChanged = true;
            }
            else
            {
                UserInEventRole uir = ccdr.GetUserInEventRole(roleSiteUser.Id, ccEvent.Id, roleName);
                if (uir != null)
                {
                    ccdr.EFContext.UsersInEventRoles.Remove(uir);
                    siteUserChanged = true;
                }
            }
        }


        private IQueryable<SiteUserListItemViewModel> GetProjectedSiteUsers(CodeCampDataRepository ccdr,
            ISiteUserSearchFiler filter, TimeSpan localTimeConversion)
        {
            if (filter == null)
                throw new ArgumentNullException("filter");

            string firstName = null;
            string lastName = null;
            if (!string.IsNullOrWhiteSpace(filter.FirstName))
                firstName = filter.FirstName;
            if (!string.IsNullOrWhiteSpace(filter.LastName))
                lastName = filter.LastName;


            IQueryable<SiteUser> initialQueryResult = null;
            if (filter.EventId.HasValue && filter.IsEventPresenter)
            {
                var siteUsers =
                    (from p in ccdr.EFContext.Presenters
                     join su in ccdr.EFContext.SiteUsers
                     on p.SiteUserId equals su.Id
                     where p.EventId == filter.EventId.Value
                     select su
                     )
                     .OrderBy(su => su.FirstName)
                    .ThenBy(su => su.LastName)
                    .ThenBy(su => su.Id);
                initialQueryResult = siteUsers;
            }
            else
            {
                //var siteUsers = ccdr.EFContext.SiteUsers
                //                    .Include("Presenters")
                //                    .Where(su => ((firstName == null) || (su.FirstName == firstName)))
                //                    .Where(su => ((lastName == null) || (su.LastName == lastName)))
                //                    .OrderBy(su => su.FirstName)
                //                    .ThenBy(su => su.LastName)
                //                    .ThenBy(su => su.Id);
                //initialQueryResult = siteUsers;
                initialQueryResult = ccdr.EFContext.SiteUsers
                                    .OrderBy(su => su.FirstName)
                                    .ThenBy(su => su.LastName)
                                    .ThenBy(su => su.Id);
            }
            if (!string.IsNullOrWhiteSpace(firstName))
            {
                initialQueryResult = initialQueryResult
                                    .Where(su => su.FirstName == firstName);
            }
            if (!string.IsNullOrWhiteSpace(lastName))
            {
                initialQueryResult = initialQueryResult
                                    .Where(su => su.LastName == lastName);
            }
            if (filter.ActiveSince.HasValue)
            {
                initialQueryResult = initialQueryResult
                                    .Where(su => su.LastOnlineActivityUTC.HasValue
                                        && su.LastOnlineActivityUTC >= filter.ActiveSince.Value);
            }

            var projectedSiteUsers = from u in initialQueryResult
                                     select new SiteUserListItemViewModel
                                     {
                                         EmailAddress = u.EmailAddress,
                                         FirstName = u.FirstName,
                                         IsApproved = u.IsApproved,
                                         IsLockedOut = u.IsLockedOut,
                                         LastLoginUTC = u.LastLoginUTC,
                                         LastName = u.LastName,
                                         LastOnlineActivityUTC = u.LastOnlineActivityUTC,
                                         SiteUserId = u.Id,
                                         UserIdentityProvider = u.UserIdentityProvider,
                                         UserIdentityClaim = u.UserIdentityClaim,
                                         PresenterId = u.Presenters
                                                        .Where(p => filter.EventId.HasValue && p.EventId == filter.EventId.Value)
                                                        .OrderByDescending(p => p.Id)
                                                        .Select(p => p.Id)
                                                        .FirstOrDefault(),
                                     };

            return projectedSiteUsers as IQueryable<SiteUserListItemViewModel>;
        }


        public ActionResult SiteUsers(SiteUserSearchViewModel model, string eventName)
        {
            SiteUsersViewModel viewModel = SiteUsers(model, eventName, false);
            return View(viewModel);
        }

        //[Authorize(Roles = CCRoles.RoleNames.BigCheeze)] //Property of class
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SiteUsers(SiteUserSearchViewModel model, string eventName, string firstName)
        {
            SiteUsersViewModel viewModel = SiteUsers(model, eventName, true);
            return View(viewModel);
        }

        private SiteUsersViewModel SiteUsers(SiteUserSearchViewModel model, string eventName, bool postback)
        {
            SetLoggerThreadContextData();
            using (CodeCampDataRepository repository = new CodeCampDataRepository())
            {
                //try
                //{
                    var ccEvent = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, this.User);
                    SetSharedViewBagProperties(ccEvent);
                    SiteUserSearchViewModel savedModel = null;
                    SiteUserSearchViewModel queryModel = null;

                    if (TempData.ContainsKey(Tags.savedFilterModel))
                    {
                        savedModel = TempData[Tags.savedFilterModel] as SiteUserSearchViewModel;
                    }

                    SiteUsersViewModel viewModel = new SiteUsersViewModel();
                    SetSharedEventProperties(ccEvent, viewModel, repository);

                    const int defaultLogEntriesPerPage = 20;

                    TimeSpan localTimeConversion = new TimeSpan(0); // LocalTimeConversion;
                    if (postback)
                    {
                        if (!string.IsNullOrWhiteSpace(model.ClearButton))
                        {
                            savedModel = null;
                            model = new SiteUserSearchViewModel
                            {
                                Page = 1,
                                RowsPerPage = defaultLogEntriesPerPage
                            };
                            ModelState.Clear();
                        }
                        else
                        {
                            if (ModelState.IsValid)
                            {
                                //New search
                                model.Page = 1;
                                queryModel = model;
                                if (model.UTCAdjustMinutes.HasValue)
                                    localTimeConversion = new TimeSpan(0, model.UTCAdjustMinutes.Value, 0);
                            }
                            else
                            {
                                if (savedModel != null)
                                {
                                    queryModel = savedModel;
                                }
                            }
                        }
                    }
                    else
                    {
                        Nullable<int> page = null;
                        if (savedModel != null)
                        {
                            if (!page.HasValue)
                                page = model.Page;
                            model = savedModel;
                            model.Page = page;
                            if (model.UTCAdjustMinutes.HasValue)
                                localTimeConversion = new TimeSpan(0, model.UTCAdjustMinutes.Value, 0);
                        }
                    }

                    if (queryModel == null)
                        queryModel = model;

                    if (ModelState.ContainsKey("FilterTimeTicks"))
                        ModelState.Remove("FilterTimeTicks");

                    viewModel.SearchResultsViewModel = model;
                    queryModel.EventId = ccEvent.Id;
                    queryModel.EventShortName = ccEvent.ShortName;
                    if (!queryModel.RowsPerPage.HasValue)
                        queryModel.RowsPerPage = 20;

                    if (postback || (savedModel != null))
                    {
                        var pageIndex = model.Page ?? 1;
                        Logger.DebugFormat("Log-List LocalTimeConversion.Hours={0}", localTimeConversion.Hours);
                        var projectedSiteUsers = GetProjectedSiteUsers(repository, queryModel, localTimeConversion);
                        viewModel.SearchResultsViewModel.SearchResults = projectedSiteUsers.ToPagedList<SiteUserListItemViewModel>(pageIndex, queryModel.RowsPerPage.Value);
                    }
                    model.FilterTime = DateTime.Now;
                    if (TempData.ContainsKey(Tags.savedFilterModel))
                    {
                        TempData[Tags.savedFilterModel] = model;
                    }
                    else
                    {
                        TempData.Add(Tags.savedFilterModel, model);
                    }

                    return viewModel;
                //}
                //catch (Exception ex)
                //{
                //    LogException("EventMgmt/SiteUsers", ex);
                //    return View("Error2");
                //}
            }
        }

#if USE_MEMBERSHIP

        public ActionResult Users(string eventName)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                var siteUser = GetSiteUser(repository, this.User, true);
                if (siteUser == null)
                    return RedirectToAction("Index");

                SetSharedViewBagProperties(event_);

                EventMgmtUsersViewModel model = new EventMgmtUsersViewModel();

                int pageIndex = 0;
                int pageSize = 100;
                int totalRecords;
                SWS.MembershipUserCollection users = SWS.Membership.GetAllUsers(pageIndex, pageSize, out totalRecords);
                model.TotalPages = 0;
                if (totalRecords > 0)
                    model.TotalPages = ((decimal)totalRecords / (pageSize));
                model.PageNumber = pageIndex + 1;
                foreach (SWS.MembershipUser user in users)
                {
                    EventMgmtUserViewModel vuser = CreateEventMgmtUserViewModel(user);

                    CCM.Presenter presenter = GetPresenter(event_.Id, siteUser);
                    if (presenter != null)
                    {
                        vuser.PresenterName = String.Concat(presenter.FirstName, " ", presenter.LastName).Trim();
                        if (string.IsNullOrEmpty(vuser.PresenterName))
                            vuser.PresenterName = "?__ ?__";
                        vuser.PresenterId = presenter.Id;
                        vuser.SiteUserId = presenter.SiteUserId;
                    }
                    model.UserList.Add(vuser);
                }

                SetSharedEventProperties(event_, model, repository);

                return View(model);
            }
        }

        //private void SetVUserRoles(EventMgmtUserViewModel vuser, SWS.MembershipUser user)
        //{
        //    //TO DO: revisit this when turning on claims auth
        //    string[] roles4User = SWS.Roles.GetRolesForUser(user.UserName);
        //    string[] rolesAvailable = SWS.Roles.GetAllRoles();
        //    vuser.SetRoles(roles4User, rolesAvailable);
        //}
#endif

        private EventMgmtUserViewModel CreateEventMgmtUserViewModel(SWS.MembershipUser user)
        {
            EventMgmtUserViewModel vuser = new EventMgmtUserViewModel
            {
                Username = user.UserName,
                UserEmailAddress = user.Email,
                UserCreationDate = user.CreationDate,
                IsApproved = user.IsApproved,
                IsLockedOut = user.IsLockedOut,
                IsOnline = user.IsOnline,
                LastActivityDate = user.LastActivityDate,
                LastLoginDate = user.LastLoginDate
            };
            Guid userGuid = Guid.Empty;
            if ((user.ProviderUserKey != null) && (user.ProviderUserKey.GetType() == typeof(System.Guid)))
            {
                userGuid = (Guid)user.ProviderUserKey;
                vuser.ProviderUserKey = userGuid.ToString();
            }
            //SetVUserRoles(vuser, user);
            return vuser;
        }

        public ActionResult UserEdit(string eventName, string id)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(event_);

                EventMgmtUserEditViewModel model = new EventMgmtUserEditViewModel();

                if (!string.IsNullOrWhiteSpace(id))
                {
                    Guid providerUserKey;

                    if (Guid.TryParse(id, out providerUserKey))
                    {
                        SWS.MembershipUser user = SWS.Membership.GetUser(providerUserKey);
                        if (user != null)
                        {
                            EventMgmtUserViewModel vuser = CreateEventMgmtUserViewModel(user);
                            model.UserViewModel = vuser;
                        }
                    }
                }

                SetSharedEventProperties(event_, model, repository);

                return View(model);
            }
        }

        //[Authorize(Roles = CCRoles.RoleNames.BigCheeze)] //Property of class
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult UserEdit(string eventName, string id, EventMgmtUserViewModel model, string[] roles)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);

                SWS.MembershipUser user = null;
                Guid providerUserKey;
                if (Guid.TryParse(model.ProviderUserKey, out providerUserKey))
                {
                    user = SWS.Membership.GetUser(providerUserKey);
                }
                if (user == null)
                    return RedirectToAction("Users");

                if (ModelState.IsValid)
                {
                    if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(model.ProviderUserKey)
                        || (id != model.ProviderUserKey))
                    {
                        return RedirectToAction("Users");
                    }

#if false
                    string[] roles4User = SWS.Roles.GetRolesForUser(user.UserName);
                    string[] rolesAvailable = SWS.Roles.GetAllRoles();
                    string[] rolesFromUI = roles;
                    if (rolesFromUI == null)
                        rolesFromUI = new string[0];

                    foreach (string role in rolesAvailable)
                    {
                        if (roles4User.Contains(role) && !rolesFromUI.Contains(role))
                        {
                            SWS.Roles.RemoveUserFromRole(user.UserName, role);
                        }
                        else if (rolesFromUI.Contains(role) && !roles4User.Contains(role))
                        {
                            SWS.Roles.AddUserToRole(user.UserName, role);
                        }
                    }
#endif
                    if (!string.IsNullOrWhiteSpace(model.UserEmailAddress)
                        && (model.UserEmailAddress != user.Email))
                    {
                        user.Email = model.UserEmailAddress;
                        SWS.Membership.UpdateUser(user);
                    }
                    return RedirectToAction("Users");
                }

                EventMgmtUserEditViewModel viewModel = new EventMgmtUserEditViewModel();
                viewModel.UserViewModel = model;
                //SetVUserRoles(model, user);

                SetSharedViewBagProperties(event_);
                SetSharedEventProperties(event_, viewModel, repository);

                return View(viewModel);
            }
        }

        public ActionResult Presenters(string eventName)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(event_);

                EventMgmtUsersViewModel model = new EventMgmtUsersViewModel();

                int pageIndex = 0;
                int pageSize = 100;
                //SWS.MembershipUserCollection users = SWS.Membership.GetAllUsers(pageIndex, pageSize, out totalRecords);
                model.TotalPages = 0;


#if true

                model.FillUserList(repository.GetQueryablePresentersListForMgmt(event_.Id)
                    .OrderBy(pr => pr.PresenterLastName)
                    .ThenBy(pr => pr.PresenterFirstName)
                    .ToList());
                int totalRecords = model.UserList.Count();
                if (totalRecords > 0)
                    model.TotalPages = ((decimal)totalRecords / (pageSize));
                model.PageNumber = pageIndex + 1;
#else
                var Presenters = repository.GetPresenters(event_.Id).OrderBy(p => p.LastName).ThenBy(p2 => p2.FirstName);

                int totalRecords = Presenters.Count();
                if (totalRecords > 0)
                    model.TotalPages = ((decimal)totalRecords / (pageSize));
                model.PageNumber = pageIndex + 1;

                foreach (var presenter in Presenters)
                {
                    EventMgmtUserViewModel vuser = new EventMgmtUserViewModel
                    {
                        PresenterId = presenter.Id,
                        PresenterCreationDate = presenter.CreatedUTC,
                        PresenterName = String.Concat(presenter.FirstName, " ", presenter.LastName).Trim(),
                        PresenterEmailAddress = presenter.EmailAddress,
                        SiteUserId = presenter.SiteUserId
                    };

                    if (presenter.SiteUserId.HasValue)
                    {
                        SiteUser siteUser = repository.GetSiteUser(presenter.SiteUserId.Value);
                        vuser.SiteUserEmailAddress = siteUser.EmailAddress;

#if USE_MEMBERSHIP
                        SWS.MembershipUser user = SWS.Membership.GetUser(siteUser.UserIdentityClaim);
                        if (user != null)
                        {
                            vuser.Username = user.UserName;
                            vuser.UserEmailAddress = user.Email;
                            vuser.UserCreationDate = user.CreationDate;
                            vuser.IsApproved = user.IsApproved;
                            vuser.IsLockedOut = user.IsLockedOut;
                            vuser.IsOnline = user.IsOnline;
                            vuser.LastLoginDate = user.LastLoginDate;
                        }
#endif
                    }

                    if (string.IsNullOrEmpty(vuser.PresenterName))
                        vuser.PresenterName = "?__ ?__";
                    model.UserList.Add(vuser);
                }
#endif

 SetSharedEventProperties(event_, model, repository);

                return View(model);
            }
        }

        public ActionResult SponsorsList(string eventName)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(event_);

                SponsorListViewModel model = new SponsorListViewModel();
                var eventSponsors = repository.GetSponsors(event_.Id).OrderBy(s => s.Name);

                // assemble model
                var sponsors = new List<SponsorEditModel>();
                foreach (var sponsor in eventSponsors)
                {
                    var size = SponsorsHelper.GetScaledImageSize(sponsor.ImageWidth, sponsor.ImageHeight);

                    sponsors.Add(
                      new SponsorEditModel
                      {
                          SponsorId = sponsor.Id,
                          Name = sponsor.Name,
                          Url = sponsor.Url,
                          ImageUrl = sponsor.ImageUrl,
                          ImageWidth = size.Width,
                          ImageHeight = size.Height
                      });
                }
                model.Sponsors = sponsors;

                SetSharedEventProperties(event_, model, repository);

                return View(model);
            }
        }

        public ActionResult SponsorAdd(string eventName)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(event_);

                SponsorEditViewModel model = new SponsorEditViewModel();
                model.Sponsor = new SponsorEditModel();
                SetSharedEventProperties(event_, model, repository);

                return View(model);
            }
        }


        //[Authorize(Roles = CCRoles.RoleNames.BigCheeze)] //Property of class
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SponsorAdd(string eventName, SponsorEditModel model)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(event_);

                if (ModelState.IsValid)
                {
                    Sponsor sponsor = new Sponsor
                    {
                        Event = event_,
                        EventId = event_.Id,
                        ImageHeight = model.ImageHeight,
                        ImageWidth = model.ImageWidth,
                        ImageUrl = model.ImageUrl,
                        Name = model.Name,
                        Url = model.Url
                    };
                    repository.EFContext.Sponsors.Add(sponsor);
                    repository.Save();
                    return RedirectToAction("SponsorsList");
                }

                SponsorEditViewModel viewModel = new SponsorEditViewModel();
                viewModel.Sponsor = new SponsorEditModel();
                SetSharedEventProperties(event_, viewModel, repository);

                return View(viewModel);
            }
        }

        public ActionResult SponsorEdit(string eventName, int id)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(event_);

                var sponsor = repository.GetSponsor(event_.Id, id);
                if (sponsor == null)
                    return RedirectToAction("SponsorsList");

                SponsorEditViewModel model = new SponsorEditViewModel();
                model.Sponsor = new SponsorEditModel
                {
                    SponsorId = sponsor.Id,
                    ImageHeight = sponsor.ImageHeight,
                    ImageUrl = sponsor.ImageUrl,
                    ImageWidth = sponsor.ImageWidth,
                    Name = sponsor.Name,
                    Url = sponsor.Url
                };
                SetSharedEventProperties(event_, model, repository);

                return View(model);
            }
        }


        //[Authorize(Roles = CCRoles.RoleNames.BigCheeze)] //Property of class
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SponsorEdit(string eventName, SponsorEditModel model)
        {
            using (var repository = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(repository, eventName, DefaultEventShortName, false);
                SetSharedViewBagProperties(event_);

                var sponsor = repository.GetSponsor(event_.Id, model.SponsorId);
                if (sponsor == null)
                    return RedirectToAction("SponsorsList");

                if (ModelState.IsValid)
                {
                    sponsor.ImageHeight = model.ImageHeight;
                    sponsor.ImageWidth = model.ImageWidth;
                    sponsor.ImageUrl = model.ImageUrl;
                    sponsor.Name = model.Name;
                    sponsor.Url = model.Url;
                    repository.Save();
                    return RedirectToAction("SponsorsList");
                }

                SponsorEditViewModel viewModel = new SponsorEditViewModel();
                viewModel.Sponsor = new SponsorEditModel();
                SetSharedEventProperties(event_, viewModel, repository);

                return View(viewModel);
            }
        }


        public ActionResult ThrowException(string eventName, string id)
        {
            using (var ccdr = new CodeCampDataRepository())
            {
                var event_ = EventsHelper.GetEvent(ccdr, eventName, DefaultEventShortName, false);
                throw new Exception(string.Format("Test Error - Event {0}, id {1}", event_.ShortName, id));
            }
        }

    }
}
